#./utils/log.py -- A module for logging.
#coding:utf-8

# Import Needs
import time
import os
import easygui
import sys
sys.path.append("..")
from constants import *

# Logger Class
class Logger:
    """
    Documation of class pylog.log.Logger
    ------------------------------------
    This is a logging class. There is a built-in module in Python Library: logging.
    ------------------------------------
    Inner Class: None
    Method: __init__()
            log()
    ------------------------------------
    __init__(self, path, mode="date", level=INFO)
        path: String. The path of the log directory, if be "&print" then print to the console.
        mode: String. The mode of the name of the logs.
            "date": log filename as date, e.g, 2021-09-24-1639226553.log    (default)
            "type": log filename as leveltype, e.g, info.log    (abandoned)
            "datetype": log inner directory as date, e.g, 2021-09-24-1639226553/debug.log   (abandoned)
            "typedate": log inner directory as type, e.g, debug/2021-09-24-1637226553.log   (abandoned)
        level: Integer(0-4). The log file's logging level.
                             DEBUG, INFO, WARNING, ERROR, FATAL.
                               0      1      2       3      4
               Logging only outputs higer level(including the same). e.g, level=1, outputs info and higher.
    ------------------------------------
    log(self, msg, level=INFO, ln=None, filename=None)
        msg: String. Message that you want to show in log.
        level: Integer(0-4). The logging line's logging level.
                             DEBUG, INFO, WARNING, ERROR, FATAL.
                               0      1      2       3      4
               Logging only outputs higer level(including the same). e.g, level=1, outputs info and higher.
        ln: Integer(0-4). Better set to inspect.getframeinfo(inspect.currentframe()).lineno
        filename: String. Better set to __file__
        logging output line: [leveltype]time-file line ln msg
                         e.g,[fatal] 2021-09-09-19:30:30 line 4 IndexError: list index out of range
    """

    # Inition
    def __init__(self, path, mode="date", level=INFO) -> None:
        # Set Self Varible
        self.path = path
        self.mode = mode
        self.level = level
        # Create File
        if self.mode == "date":  # Mode: date
            tstrd = time.strftime("%Y-%m-%d")
            fn = "{}-{}.log".format(tstrd, int(time.time()))    # 2021-09-08-1637226553.log
            if (self.path != "&print") and (self.path != "&win"):
                # Create directory if not exists.
                pth = os.path.join(self.path, fn)
                self.fn = pth
                spllited = pth.split("/")
                spllited.pop(-1)
                pthd = "/".join(spllited)
                if not os.path.exists(pthd):   # Check if exists.
                    os.makedirs(pthd)
                elif len(os.listdir(pthd)) > 10:
                    for f in os.listdir(pthd):
                        os.remove(os.path.join(pthd,f))
                return None
        elif self.mode == "type":   # Mode: type
            raise ValueError("mode type has been abandoned")   # abandoned
        elif self.mode == "datetype":   # Mode: datetype
            raise ValueError("mode datetype has been abandoned")   # abandoned
        elif self.mode == "typedate":   # Mode: typedate
            raise ValueError("typemode type has been abandoned")   # abandoned
        else:   # Mode: not found
            raise ValueError("log mode should be \"date\" or \"type\" or \"datetype\" or \"typedate\"")

    # Log Function
    def log(self, msg, level=INFO, ln=None, filename=None) -> None:
        if level < self.level:  # Check logging level is(not) higher.
            return None
        tstr = time.strftime("%Y.%m.%d-%H:%M:%S")   # 2020.09.01-20:00:06
        lgstr = "[{}]{}-{} line{} {}\n".format(LEVEL[level], tstr, filename, ln, msg)
                # [debug]2009-08-24-19:30:06 line4 testing log
        if self.path == "&print":   # Path: &print
            print(lgstr)
            return None
        elif self.path == "&win":   # Path: &win
            easygui.msgbox(msg, LEVEL[level])
            return None
        else:
            with open(self.fn, mode='a') as f:
                f.write(lgstr)
       

# LoggerSet Class
class LoggerSet:
    """
    Documentation of class pylog.log.LoggerSet
    ------------------------------------------
    This is a set to collect Loggers.
    ------------------------------------------
    Inner Class: None
    Method: __init__()
            log()
    ------------------------------------------
    __init__(self, *args)
        *args: Put all Loggers in this argument.
    ------------------------------------------
    log(self, msg, level=INFO, ln=None, filename=None)
        All arguments are sent to Logger.log().
    """

    # Inition
    def __init__(self, *args) -> None:
        self.args = args

    # Log Function
    def log(self, msg, level=INFO, ln=None, filename=None):
        for l in self.args: # Circulate the list of Loggers.
            l.log(msg=msg, level=level, ln=ln, filename=filename)   # Log them each.